home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue57 / alfresco / tststr3.dpr < prev    next >
Encoding:
Text File  |  2000-04-08  |  4.4 KB  |  151 lines

  1. program tststr3;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   Windows,
  7.   SysUtils;
  8.  
  9. function PosCh(aCh : char; const S : string; aStart : integer) : integer;
  10. var
  11.   i : integer;
  12. begin
  13.   if aStart < 1 then
  14.     aStart := 1;
  15.   for i := aStart to length(S) do
  16.     if (S[i] = aCh) then begin
  17.       Result := i;
  18.       Exit;
  19.     end;
  20.   Result := 0;
  21. end;
  22.  
  23. function ConvertEscapes1(const aSt : string) : string;
  24. var
  25.   i : integer;
  26.   PosEscape: integer;
  27.   ASCIIStr : string;
  28.   ASCIIVal : integer;
  29.   ec       : integer;
  30. begin
  31.   Result := aSt;
  32.   i := 1;
  33.   while i <= length(Result) do begin
  34.     {find the next escape character in the remaining string}
  35.     PosEscape := PosCh('\', Result, i);
  36.     {if there is no escape, exit}
  37.     if (PosEscape = 0) then
  38.       Exit;
  39.     {if this position is right at the end of the string, exit, we're
  40.      done}
  41.     if PosEscape = length(Result) then
  42.       Exit;
  43.     {if the next character is an backslash, then replace the double
  44.      backslash by just one of them}
  45.     if (Result[PosEscape+1] = '\') then
  46.       Delete(Result, PosEscape, 1)
  47.     {if the next character is a digit, there should be three of them,
  48.      convert the four characters \nnn to an ASCII character, ignore
  49.      all errors (ie, don't convert the backslash)}
  50.     else if (Result[PosEscape+1] in ['0'..'9']) and
  51.             (PosEscape <= length(Result) - 3) then begin
  52.       ASCIIStr := Copy(Result, PosEscape+1, 3);
  53.       Val(ASCIIStr, ASCIIVal, ec);
  54.       if (ec = 0) and (ASCIIVal <= 255) then begin
  55.         Delete(Result, PosEscape, 4);
  56.         Insert(char(ASCIIVal), Result, PosEscape);
  57.       end;
  58.     end;
  59.     i := PosEscape + 1;
  60.   end;
  61. end;
  62.  
  63. function ConvertEscapes(const aSt : string) : string;
  64. var
  65.   DestInx   : integer;
  66.   SourceInx : integer;
  67.   ASCIIStr  : string;
  68.   ASCIIVal  : integer;
  69.   ec        : integer;
  70. begin
  71.   {assume that we won't convert any escapes: the result string will be
  72.    the same length as the source}
  73.   SetLength(Result, length(aSt));
  74.   {go through the source, character by character}
  75.   DestInx := 0;
  76.   SourceInx := 1;
  77.   while SourceInx <= length(aSt) do begin
  78.     {non-escape characters pass straight through}
  79.     if (aSt[SourceInx] <> '\') then begin
  80.       inc(DestInx);
  81.       Result[DestInx] := aSt[SourceInx];
  82.       inc(SourceInx);
  83.     end
  84.     {otherwise it's an escape character}
  85.     else begin
  86.       {if the escape is at the end of the source string, pass it
  87.        through--there cannot be any other characters to convert}
  88.       if (SourceInx = length(aSt)) then begin
  89.         inc(DestInx);
  90.         Result[DestInx] := '\';
  91.         inc(SourceInx);
  92.       end
  93.       {if it's the first of a double escape, pass a single one
  94.        through to the result string}
  95.       else if (aSt[SourceInx+1] = '\') then begin
  96.         inc(DestInx);
  97.         Result[DestInx] := '\';
  98.         inc(SourceInx, 2);
  99.       end
  100.       else if (aSt[SourceInx+1] in ['0'..'9']) and
  101.               (SourceInx <= length(aSt) - 3) then begin
  102.         ASCIIStr := Copy(aSt, SourceInx+1, 3);
  103.         Val(ASCIIStr, ASCIIVal, ec);
  104.         if (ec = 0) and (ASCIIVal <= 255) then begin
  105.           inc(DestInx);
  106.           Result[DestInx] := char(ASCIIVal);
  107.           inc(SourceInx, 4);
  108.         end;
  109.       end
  110.       {otherwise it *is* an escape character, but part of a badly
  111.        formed sequence: just pass it through}
  112.       else begin
  113.         inc(DestInx);
  114.         Result[DestInx] := '\';
  115.         inc(SourceInx);
  116.       end;
  117.     end;
  118.   end;
  119.   {finally set the correct length of the result: DestInx is the index
  120.    of the last character written}
  121.   SetLength(Result, DestInx);
  122. end;
  123.  
  124.  
  125. var
  126.   i : integer;
  127.   StartTime : DWORD;
  128. begin
  129.   writeln(ConvertEscapes1('abc\055'));
  130.   writeln(ConvertEscapes1('abc\\\055'));
  131.   writeln(ConvertEscapes1('abc\\\055\'));
  132.   writeln(ConvertEscapes1('abc\\\055\a\056'));
  133.   writeln(ConvertEscapes('abc\055'));
  134.   writeln(ConvertEscapes('abc\\\055'));
  135.   writeln(ConvertEscapes('abc\\\055\'));
  136.   writeln(ConvertEscapes('abc\\\055\a\056'));
  137.  
  138.   writeln('testing normal routine...');
  139.   StartTime := GetTickCount;
  140.   for i := 1 to 100000 do
  141.     ConvertEscapes1('\048\049\050\051\052\053\054\055\056\057');
  142.   writeln('time taken: ', GetTickCount - StartTime);
  143.  
  144.   writeln('testing faster routine...');
  145.   StartTime := GetTickCount;
  146.   for i := 1 to 100000 do
  147.     ConvertEscapes('\048\049\050\051\052\053\054\055\056\057');
  148.   writeln('time taken: ', GetTickCount - StartTime);
  149.   readln;
  150. end.
  151.